// file:arch/x86/arch/cpu/segment.c
// autor: jiang xinpeng
// time:2021.2.2
// copyright:(C) 2020-2050 by jiangxinpeng,All right are reserved.

#include <arch/segment.h>
#include <arch/descript.h>
#include<arch/memory.h>
#include <arch/tss.h>
#include <arch/page.h>
#include <os/debug.h>
#include <lib/string.h>

volatile des_t *gdt = GDT_VADDRESS;

#pragma GCC optimize("O0")

void SegmentDescriptInit()
{
    volatile des_t descript;

    // clear gdt date
    memset(gdt, 0, sizeof(des_t) * 255);


    // init kernel code segment descript
    SegmentDescriptInstall(0x00000000, 0xfffff, SEG_ATTRIBUTE_32BITSOPMODE | SEG_ATTRIBUTE_4KBGRAN | SEG_ATTRIBUTE_PRESENT | SEG_ATTRIBUTE_COMMONSEG | SEG_ATTRIBUTE_DPL0, SEG_CODE_TYPE_EXE, SEG_SEL_KERNEL_CODE);

    // init kenel data segment descript
    SegmentDescriptInstall(0x00000000, 0xfffff, SEG_ATTRIBUTE_32BITSOPMODE | SEG_ATTRIBUTE_4KBGRAN | SEG_ATTRIBUTE_PRESENT | SEG_ATTRIBUTE_COMMONSEG | SEG_ATTRIBUTE_DPL0, SEG_DATA_TYPE_READ | SEG_DATA_TYPE_WRITE, SEG_SEL_KERNEL_DATA);

    // init user code segment descript
    SegmentDescriptInstall(0x00000000, 0xfffff, SEG_ATTRIBUTE_32BITSOPMODE | SEG_ATTRIBUTE_4KBGRAN | SEG_ATTRIBUTE_PRESENT | SEG_ATTRIBUTE_COMMONSEG | SEG_ATTRIBUTE_DPL3, SEG_CODE_TYPE_EXE, SEG_SEL_USER_CODE);

    // init user data segment descript
    SegmentDescriptInstall(0x00000000, 0xfffff, SEG_ATTRIBUTE_32BITSOPMODE | SEG_ATTRIBUTE_4KBGRAN | SEG_ATTRIBUTE_PRESENT | SEG_ATTRIBUTE_COMMONSEG | SEG_ATTRIBUTE_DPL3, SEG_DATA_TYPE_READ | SEG_DATA_TYPE_WRITE, SEG_SEL_USER_DATA);

    // install tss0 descript
    SegmentDescriptInstall(&tss0, sizeof(tss_t), SEG_ATTRIBUTE_4KBGRAN | SEG_ATTRIBUTE_PRESENT | SEG_ATTRIBUTE_SYSSEGMENT | SEG_ATTRIBUTE_DPL0, SEG_TYPE_TSSFREE, SEG_SEL_TSS);

    // update GDTR to enable page
    LoadGDTR(GDT_LIMIT, GDT_VADDRESS);
    KPrint("[segment] segment descript init done\n");
}

void SegmentDescriptInstall(uint32_t base, uint32_t limit, uint8_t attr, uint8_t type, uint8_t sel)
{
    des_t descript;

    descript = MakeDescript(base, limit, attr, type);
    InstallDescriptTo(descript, SEL_INDEX_MASK(sel), (uint32_t)gdt);
}
